﻿using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Diagnostics;

namespace BuildExplorer
{
    class Clock
    {
        public string TzRegKeyName { get; private set; }
        public string DisplayName { get; private set; }

        private static Dictionary<string, Clock> clocks;
        public static Dictionary<string, Clock> Clocks
        {
            get
            {
                if (clocks == null)
                {
                    clocks = new Dictionary<string, Clock>();
                    clocks.Add(string.Empty, new Clock() { DisplayName = "Local", TzRegKeyName = string.Empty } );  // Implicit Local clock

                    RegistryKey clockKeys = Registry.CurrentUser.OpenSubKey(@"Control Panel\TimeDate\AdditionalClocks");
                    if (clockKeys != null)
                    {
                        foreach (string subKeyName in clockKeys.GetSubKeyNames())
                        {
                            var clock = new Clock(clockKeys.OpenSubKey(subKeyName));
                            clocks.Add(clock.TzRegKeyName, clock);
                        }
                    }
                }

                return clocks;
            }
        }

        public static Clock GetClock(string TzRegKeyName)
        {
            Clock res;
            if (Clocks.TryGetValue(TzRegKeyName, out res))
            {
                return res;
            }

            // Timezone is not in additional clocks - add it with TzRegKeyName as display name, that's all we have
            Clock bogusClock = new Clock() { DisplayName = TzRegKeyName, TzRegKeyName = TzRegKeyName };
            clocks.Add(TzRegKeyName, bogusClock);
            return bogusClock;
        }

        private Clock() { }

        private Clock(RegistryKey registryKey)
        {
            Debug.Assert(registryKey != null);

            this.TzRegKeyName = (string)registryKey.GetValue("TzRegKeyName");
            this.DisplayName = (string)registryKey.GetValue("DisplayName");
        }

        private TimeZoneInfo tzi;
        public TimeZoneInfo TimeZoneInfo
        {
            get
            {
                if (tzi == null)
                {
                    if (string.IsNullOrEmpty(this.TzRegKeyName))
                    {
                        tzi = TimeZoneInfo.Local;
                    }
                    else
                    {
                        try
                        {
                            tzi = TimeZoneInfo.FindSystemTimeZoneById(this.TzRegKeyName);
                        }
                        catch (TimeZoneNotFoundException)
                        {
                            tzi = TimeZoneInfo.Local;  // Corrupt settings ==> Local
                        }
                    }
                }

                return tzi;
            }
        }

        public string GetFullDisplayName()
        {
            if (this.TzRegKeyName == "UTC")
            {
                return "UTC";  // No need to show offsets for UTC
            }

            DateTime now = DateTime.Now;  // DateTime.Parse("2013-10-28");
            TimeSpan offset = this.TimeZoneInfo.GetUtcOffset(now);
            return string.Format(@"{0} - (UTC{1}{2:hh\:mm}) {3}",
                this.DisplayName,
                (offset >= TimeSpan.Zero) ? "+" : "-",
                offset,
                this.TimeZoneInfo.IsDaylightSavingTime(now) ? this.TimeZoneInfo.DaylightName : this.TimeZoneInfo.StandardName);
        }
    }
}
